package com.hancheng.commoncloud.framework.aop;

import cn.hutool.core.util.StrUtil;
import com.hancheng.commoncloud.framework.result.Response;
import com.hancheng.commoncloud.framework.result.exception.CommonException;
import com.hancheng.commoncloud.framework.result.exception.ResultCode;
import com.hancheng.commoncloud.framework.util.LocalUserInfoUtil;
import com.hancheng.commoncloud.framework.util.ValidatorUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 全局异常处理,在这里捕获的是将要抛给 JVM 的异常，这些异常会返回给调用者，而我们不希望调用者看到这些数据，在这里屏蔽
 *
 * @author:
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(Exception.class)
    public Response<Void> handleException(Exception exception) {
        log.error("全局异常, ", exception);
        LocalUserInfoUtil.remove();
        return Response.error(ValidatorUtils.message("系统异常,请稍后再试"));
    }

    @ExceptionHandler(CommonException.class)
    public Response<Void> handleCommonException(CommonException commonException) {
        Integer code = Optional.ofNullable(commonException.getErrcode()).orElse(ResultCode.FAILED.getCode());
        Response<Void> response = Response.error(code, ValidatorUtils.message(commonException.getMessage()));
        LocalUserInfoUtil.remove();
        return response;
    }

    @ExceptionHandler(IllegalArgumentException.class)
    public Response<Void> handleIllegalArgumentException(IllegalArgumentException illegalArgumentException) {
        log.error("全局异常, 消息:", illegalArgumentException);

        LocalUserInfoUtil.remove();
        return Response.error(ValidatorUtils.message(illegalArgumentException.getMessage()));
    }

    /**
     * 捕获 @Valid 参数校验异常
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Response<Void> handleMethodArgumentNotValidException(MethodArgumentNotValidException methodArgumentNotValidException) {
        List<String> errorList = methodArgumentNotValidException.getBindingResult().getFieldErrors()
                .stream().map(error -> {
                    String rawMessage = error.getDefaultMessage();
                    if (StrUtil.isNotBlank(rawMessage) && rawMessage.startsWith("{") && rawMessage.endsWith("}")) {
                        // 不为空，且为占位符才需要国际化
                        String key = rawMessage.substring(1, rawMessage.length() - 1);
                        return ValidatorUtils.message(key, error.getArguments());
                    } else {
                        // 否则原样返回
                        return rawMessage;
                    }
                }).collect(Collectors.toList());
        LocalUserInfoUtil.remove();
        return Response.error(String.join("；", errorList));
    }
}
